from commands import add
from array import array
from twisted.internet import reactor
from pyspades.server import block_action, set_color, Flag, tc_data, territory_capture
from pyspades.constants import *
from pyspades.common import make_color

TOWER_GREY = [(0 , 0 , 1), (-2 , -2 , 1), (-1 , -2 , 1), (0 , -2 , 1), (1 , -2 , 1), (2 , -2 , 1), (-2 , 2 , 1), (-1 , 2 , 1), (0 , 2 , 1), (1 , 2 , 1), (2 , 2 , 1), (-2 , -1 , 1), (-2 , 0 , 1), (-2 , 1 , 1), (2 , -1 , 1), (2 , 0 , 1), (2 , 1 , 1), 
(-2 , -2 , 0), (-1 , -2 , 0), (0 , -2 , 0), (1 , -2 , 0), (2 , -2 , 0), (-2 , 2 , 0), (-1 , 2 , 0), (0 , 2 , 0), (1 , 2 , 0), (2 , 2 , 0), (-2 , -1 , 0), (-2 , 0 , 0), (-2 , 1 , 0), (2 , -1 , 0), (2 , 0 , 0), (2 , 1 , 0), 
(-2 , -2 , -1), (-1 , -2 , -1), (0 , -2 , -1), (1 , -2 , -1), (2 , -2 , -1), (-2 , -1 , -1), (-1 , -1 , -1), (0 , -1 , -1), (1 , -1 , -1), (2 , -1 , -1), (-2 , 0 , -1), (-1 , 0 , -1), (1 , 0 , -1), (2 , 0 , -1), (-2 , 1 , -1), (-1 , 1 , -1), (0 , 1 , -1), (1 , 1 , -1), (2 , 1 , -1), (-2 , 2 , -1), (-1 , 2 , -1), (0 , 2 , -1), (1 , 2 , -1), (2 , 2 , -1), 
(-2 , -2 , -2), (-1 , -2 , -2), (0 , -2 , -2), (1 , -2 , -2), (2 , -2 , -2), (-2 , -1 , -2), (-1 , -1 , -2), (0 , -1 , -2), (1 , -1 , -2), (2 , -1 , -2), (-2 , 0 , -2), (-1 , 0 , -2), (1 , 0 , -2), (2 , 0 , -2), (-2 , 1 , -2), (-1 , 1 , -2), (0 , 1 , -2), (1 , 1 , -2), (2 , 1 , -2), (-2 , 2 , -2), (-1 , 2 , -2), (0 , 2 , -2), (1 , 2 , -2), (2 , 2 , -2), 
(-2 , -2 , -3), (-1 , -2 , -3), (0 , -2 , -3), (1 , -2 , -3), (2 , -2 , -3), (-2 , -1 , -3), (-1 , -1 , -3), (0 , -1 , -3), (1 , -1 , -3), (2 , -1 , -3), (-2 , 0 , -3), (-1 , 0 , -3), (1 , 0 , -3), (2 , 0 , -3), (-2 , 1 , -3), (-1 , 1 , -3), (0 , 1 , -3), (1 , 1 , -3), (2 , 1 , -3), (-2 , 2 , -3), (-1 , 2 , -3), (0 , 2 , -3), (1 , 2 , -3), (2 , 2 , -3), 
(2 , 2 , -4), (-2 , 2 , -4), (2 , -2 , -4), (-2 , -2 , -4), (0 , 0 , -4),
(2 , 2 , -5), (-2 , 2 , -5), (2 , -2 , -5), (-2 , -2 , -5), 
(2 , 2 , -6), (-2 , 2 , -6), (2 , -2 , -6), (-2 , -2 , -6), 
(-2 , -2 , -7), (-1 , -2 , -7), (0 , -2 , -7), (1 , -2 , -7), (2 , -2 , -7), (-2 , -1 , -7), (-1 , -1 , -7), (0 , -1 , -7), (1 , -1 , -7), (2 , -1 , -7), (-2 , 0 , -7), (-1 , 0 , -7), (0 , 0 , -7), (1 , 0 , -7), (2 , 0 , -7), (-2 , 1 , -7), (-1 , 1 , -7), (0 , 1 , -7), (1 , 1 , -7), (2 , 1 , -7), (-2 , 2 , -7), (-1 , 2 , -7), (0 , 2 , -7), (1 , 2 , -7), (2 , 2 , -7)]
TOWER_TEAM = [(2 , 2 , -8), (-2 , 2 , -8), (2 , -2 , -8), (-2 , -2 , -8), (0 , 0 , -8)]
TOWER_LASR = [(0 , 0 , -9), (0 , 0 , -10), (0 , 0 , -11), (0 , 0 , -12), (0 , 0 , -13), (0 , 0 , -14), (0 , 0 , -15), (0 , 0 , -16), (0 , 0 , -17), (0 , 0 , -18), (0 , 0 , -19), (0 , 0 , -20), (0 , 0 , -21), (0 , 0 , -22)]

class Territory(Flag):
    progress = 0.0
    players = None
    start = None
    rate = 0
    rate_value = 0.0
    finish_call = None
    capturing_team = None
    tower_id = 0
    activated = True
    
    def __init__(self, *arg, **kw):
        Flag.__init__(self, *arg, **kw)
        self.players = set()
    
    def add_player(self, player):
        return
        
    def remove_player(self, player):
        return
    
    def update_rate(self):
        return
    
    def send_progress(self):
        return
    
    def set_team(self, cap_player):
        team = cap_player.team
        team.score += 1
        if self.team is not None:
            self.team.score -= 1
        self.team = team
        if team.score >= self.protocol.max_score:
            for tc_tower in self.protocol.entities:
                cap_player.break_tower(tc_tower.x,tc_tower.y,tc_tower.z)
            self.protocol.reset_game(territory = self)
        else:
            cap_player.cap_tower(self.x,self.y,self.z)
            territory_capture.object_index = self.id
            territory_capture.state = self.team.id
            territory_capture.winning = False
            self.protocol.send_contained(territory_capture)
       
    def get_progress(self, set = False):
        return

def apply_script(protocol, connection, config):
    class TowerTCConnection(connection):
        def on_block_build_attempt(self, x, y, z):
            for tc_tower in self.protocol.entities:
                sx, sy, sz = tc_tower.x, tc_tower.y, tc_tower.z
                if x == sx and y == sy:
                    if tc_tower.team != self.team:
                        tc_tower.set_team(self)
                    elif tc_tower.activated == False:
                        self.cap_tower(x,y,sz)
                        tc_tower.activated = True
                    else:
                        self.send_chat('Your team already captured this tower!')
                    return False
                if x > sx - 4 and x < sx + 4 and y > sy - 4 and y < sy + 4:
                    return False
            return connection.on_block_build_attempt(self, x, y, z)

        def cap_tower(self,x,y,z):
            self.break_tower(x,y,z)
            reactor.callLater(0.25,self.build_tower,x,y,z)
        def break_tower(self,x,y,z):
            for block in TOWER_TEAM:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    block_action.value = DESTROY_BLOCK
                    block_action.x,block_action.y,block_action.z = x+bx, y+by, z+bz
                    self.protocol.send_contained(block_action)
                    self.protocol.map.remove_point(x+bx, y+by, z+bz)
        def build_tower(self,x,y,z):
            set_color.value = make_color(self.team.color[0], self.team.color[1], self.team.color[2])
            set_color.player_id = self.player_id
            self.send_contained(set_color)
            block_action.value = BUILD_BLOCK
            for block in TOWER_TEAM:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    block_action.x,block_action.y,block_action.z = x+bx, y+by, z+bz
                    self.protocol.send_contained(block_action, save = True)
                    self.protocol.map.set_point(x+bx, y+by, z+bz, self.team.color + (255,), user = False)
            for block in TOWER_LASR:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    block_action.x,block_action.y,block_action.z = x+bx, y+by, z+bz
                    self.protocol.send_contained(block_action, save = True)
                    self.protocol.map.set_point(x+bx, y+by, z+bz, self.team.color + (255,), user = False)

    class TowerTCProtocol(protocol):
        def reset_tc(self):
            if self.entities is None:
                self.entities = []
            # cool algorithm number 1
            land_count = self.map.count_land(0, 0, 512, 512)
            territory_count = int((land_count/(512.0 * 512.0))*(
                MAX_TERRITORY_COUNT-MIN_TERRITORY_COUNT) + MIN_TERRITORY_COUNT)
            j = 512.0 / territory_count
            if self.entities == []:
                for i in xrange(territory_count):
                    x1 = i * j
                    y1 = 512 / 4
                    x2 = (i + 1) * j
                    y2 = y1 * 3
                    flag = Territory(i, self, *self.get_random_location(
                        zone = (x1, y1, x2, y2)))
                    flag.tower_id = i
                    if i < territory_count / 2:
                        team = self.blue_team
                    elif i > (territory_count-1) / 2:
                        team = self.green_team
                    else:
                        # odd number - neutral
                        team = None
                    if team == None:
                        tower_color = (255,255,255,255)
                    else:
                        tower_color = team.color + (255,)
                    self.build_tower(tower_color,flag.x,flag.y,flag.z)
                    flag.team = team
                    if team is None:
                        flag.progress = 0.5
                    else:
                        team.score += 1
                        flag.progress = float(team.id)
                    self.entities.append(flag)
                    tc_data.set_entities(self.entities)
            else:
                for tc_tower in self.entities:
                    tc_tower.activated = False
                    if tc_tower.tower_id < territory_count / 2:
                        team = self.blue_team
                    elif tc_tower.tower_id > (territory_count-1) / 2:
                        team = self.green_team
                    else:
                        # odd number - neutral
                        team = None
                    tc_tower.team = team
                    if team is None:
                        tc_tower.progress = 0.5
                    else:
                        team.score += 1
                        tc_tower.progress = float(team.id)
                    tc_data.set_entities(self.entities)
            self.max_score = territory_count
            protected = None

        def is_indestructable(self, x, y, z):
            for tc_tower in self.entities:
                sx, sy, sz = tc_tower.x, tc_tower.y, tc_tower.z
                if x > sx - 4 and x < sx + 4 and y > sy - 4 and y < sy + 4:
                    return True
            return protocol.is_indestructable(self, x, y, z)

        def build_tower(self,tower_color,x,y,z):
            for block in TOWER_GREY:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    self.map.set_point(x+bx, y+by, z+bz, (128,128,128,255), user = False)
            for block in TOWER_TEAM:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    self.map.set_point(x+bx, y+by, z+bz, tower_color, user = False)
            for block in TOWER_LASR:
                bx, by, bz = block[0], block[1], block[2]
                if x+bx > 0 and x+bx < 512 and y+by > 0 and y+by < 512 and z+bz > 0 and z+bz < 62:
                    self.map.set_point(x+bx, y+by, z+bz, tower_color, user = False)
    return TowerTCProtocol, TowerTCConnection